#include "burnpipe.h"

using burn::CStatus;
using burn::GElementPtr;
using burn::GPipelineFactory;
using burn::GPipelinePtr;
using burn::BLOG;

class NodeDet : public burn::GNode {
public:
  CStatus run() override {
    CStatus status;
    BLOG("this is node: %s, this node cost 3s", this->getName().c_str());
    CGRAPH_SLEEP_SECOND(3);
    return status;
  }
};

class NodeHand : public burn::GNode {
public:
  CStatus run() override {
    CStatus status;
    BLOG("this is node: %s, this node cost 2s", this->getName().c_str());
    CGRAPH_SLEEP_SECOND(2);
    return status;
  }
};

class NodeBody3D : public burn::GNode {
public:
  CStatus run() override {
    CStatus status;
    BLOG("this is node: %s, cost 2s", this->getName().c_str());
    CGRAPH_SLEEP_SECOND(2);
    return status;
  }
};

class NodeFusion : public burn::GNode {
public:
  CStatus run() override {
    CStatus status;
    BLOG("this is node: %s, final part cost 2s", this->getName().c_str());
    CGRAPH_SLEEP_SECOND(2);
    return status;
  }
};

void main_pipe() {
  GPipelinePtr pipe = GPipelineFactory::create();

  GElementPtr a, b, c, d = nullptr;

  CStatus status = pipe->registerGElement<NodeDet>(&a, {}, "NodeDet");
  status += pipe->registerGElement<NodeHand>(&b, {}, "NodeHand");
  status += pipe->registerGElement<NodeBody3D>(&c, {a}, "NodeBody3D");
  status += pipe->registerGElement<NodeFusion>(&d, {b, c}, "NodeFusion");

  status += pipe->init();

  std::cout << status.getInfo();

  if (!status.isOK()) {
    BLOG("register failed! info: %s", status.getInfo().c_str());
    return;
  }

  for (int i = 0; i < 20; ++i) {
    BPTIMER_START(one);
    status += pipe->run();
    BPTIMER_STOP(one);
    BLOG("run for frame: %d, current status: %d, cost: %f , [should be: 13s]", i, status.getCode(),
        BPTIMER_MSEC(one) / 1000.);
  }

  status += pipe->destroy();
  GPipelineFactory::remove(pipe);
}

int main() {
  main_pipe();
  return 0;
}